#ifndef SESSION_H
#define SESSION_H

#include "pjsipwrapper.h"

#include <qthread.h>
#include <string>

class UserHandler;
class Session;

class SessionInfo : public PjApiCallInfo
{
};

class SessionCallback : public QObject
{
    Q_OBJECT

public:

    SessionCallback(Session *session) { m_session = session;}

    ~SessionCallback() {}

    /** Call back from handler
     *  Role: UAS
     */
    // service request to handler the request by service instance.
    void serviceRequestReceived(const std::string service_name,
                                const std::string content_type,
                                unsigned long long content_length,
                                const void *data);

    /** Call back from service
     *  Role: UAC
     */
    // response received and will notify the application the data received.
    void serviceResponseReceived(const std::string service_name,
                                const std::string content_type,
                                unsigned long long content_length,
                                const void *data);

    void imReceived(const std::string from,
                        const std::string to,
                        const std::string contact,
                        const std::string mime_type,
                        const std::string body);

    void imTypingReceived(std::string from,
                        std::string to,
                        std::string contact,
                        bool isTyping);

    void serviceInfoReceived(const std::string content_type, unsigned long long content_length, const void *data);

private:

    Session *m_session;
};

#include <QMutexLocker>
#include <QMutex>

class Session : public QThread
{
    Q_OBJECT
public:

    Session(int session_id, UserHandler *handler);

    ~Session();

    void run();

    const std::string getLocalUri();

    const std::string getLocalContact();

    const std::string getRemoteContact();

    const std::string getRemoteUri();

    int getSessionID()const
    {
        return m_sessionID;
    }

    SessionCallback *getSessionCallback()const
    {
        return m_callback;
    }

    UserHandler *getUserHandler() const
    {
        return m_userHandler;
    }

    void sendIM(std::string mime_type, std::string content);

    void sendIMTyping(bool is_typing);

    void sendServiceInfo(const std::string content_type,
                        unsigned long long content_length,
                        const void *data);

    void sendServiceInfoSignal(const std::string info_html);


signals:

    void serviceInfo(const std::string service_html);

public slots:

     /**
     ***************************************
     * Service Name Format:                *
     * ---------------------------------   *
     * | Request  | Name | Request ID |    *
     * ---------------------------------   *
     * Example:                            *
     * ---------------------------------   *
     * | Request  | Blog |  12345 |        *
     * ---------------------------------   *
     ***************************************
     */


    /** Received service's response and send the response to the remote
     *  Role: UAS
     */
    void sendServiceResponse(const std::string service_name,
                            const std::string content_type,
                            unsigned long long content_length,
                            const void *data);

    /** Received client's request and send the request to the remote
     *  Role: UAC
     */
    void sendServiceRequest(const std::string name,
                        const std::string content_type,
                        unsigned long long content_length,
                        const void *data );

private:

    void initSessionInfo();

    PjApiCallInfo *m_info;

    SessionCallback *m_callback;

    int m_sessionID;

    UserHandler *m_userHandler;

    QMutex *m_mutex;

};

#endif
